﻿--[[
	Widget name	  	PropertySet
	Author     	 	Kurapica
--]]

-- PropertySet
do
	IGAS:NewAddon("IGAS_Studio")

    ------------------------------------------------------
	-- PropertySet
	------------------------------------------------------
	local _WidgetName = "PropertySet"
    local _Base = "Frame"

    -- Scripts
	local _FrameBackdrop = {
        bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
        edgeFile = "Interface\\ChatFrame\\CHATFRAMEBACKGROUND",
        tile = true, tileSize = 16, edgeSize = 1,
        insets = { left = 3, right = 3, top = 3, bottom = 3 }
	}
	local _FrameBackdrop1 = {
        bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
        edgeFile = "Interface\\ChatFrame\\CHATFRAMEBACKGROUND",
        tile = true, tileSize = 16, edgeSize = 16,
        insets = { left = 1, right = 1, top = 1, bottom = 1 }
	}

	local nodeHeight = 26
	local nodeIndent = 10

	local function SetProperty(obj, prop, value)
		obj[prop] = value
	end

	local function SetPropValue(self)
		if self.Parent.__Object and self.Parent.__Property then
			local property = GetTrueObject(self.Parent.__Object).Property[self.Parent.__Property]
			local propType = IGAS:GetPropertyType(property.Type)

			local oldvalue = self.Parent.__Object[self.Parent.__Property]
			local value

			if propType["Type"] == "number" then
				-- If the property's type is number
				value = tonumber(self.Text)
				if not value then
					-- Need reset.
					self.Text = string.format("%.1f", oldvalue or 0)
				else					
					if oldvalue == value then
						return
					end

					-- Set the property
					pcall(SetProperty, self.Parent.__Object, self.Parent.__Property, value)
					-- Refresh, maybe changed while setting a new value.
					self.Text = string.format("%.1f", self.Parent.__Object[self.Parent.__Property] or 0)
					-- Fire OnPropertyChanged
					if self.Parent.__Object[self.Parent.__Property] ~= oldvalue then
						self.Parent:Fire("OnPropertyChanged", self.Parent.__Object, self.Parent.__Property, value, oldvalue)
					end
				end

			elseif propType["Type"] == "string" then
				-- If the property's type is string
				value = tostring(self.Text or "")

				if oldvalue == value then
					return
				end

				-- Set the property
				pcall(SetProperty, self.Parent.__Object, self.Parent.__Property, value)
				-- Refresh, maybe changed while setting a new value.
				self.Text = tostring(self.Parent.__Object[self.Parent.__Property])
				-- Fire OnPropertyChanged
				if self.Parent.__Object[self.Parent.__Property] ~= oldvalue then
					self.Parent:Fire("OnPropertyChanged", self.Parent.__Object, self.Parent.__Property, value, oldvalue)
				end

			elseif propType["Type"] == "boolean" then
				-- If the property's type is boolean
				value = (self.Value and true) or false
				if oldvalue == value then
					return
				end

				-- Set the property
				pcall(SetProperty, self.Parent.__Object, self.Parent.__Property, value)
				-- Refresh, maybe changed while setting a new value.
				self.Text = tostring((self.Parent.__Object[self.Parent.__Property] and true) or false)
				-- Fire OnPropertyChanged
				if self.Parent.__Object[self.Parent.__Property] ~= oldvalue then
					self.Parent:Fire("OnPropertyChanged", self.Parent.__Object, self.Parent.__Property, value, oldvalue)
				end

			elseif propType["Type"] == "enum" then
				-- If the property's type is enum
				value = self.Text
				if oldvalue == value then
					return
				end
				-- Set the property
				pcall(SetProperty, self.Parent.__Object, self.Parent.__Property, value)
				-- Refresh, maybe changed while setting a new value.
				self.Text = tostring(self.Parent.__Object[self.Parent.__Property])
				-- Fire OnPropertyChanged
				if self.Parent.__Object[self.Parent.__Property] ~= oldvalue then
					self.Parent:Fire("OnPropertyChanged", self.Parent.__Object, self.Parent.__Property, value, oldvalue)
				end
			end
		end
	end

	local function GetPropValue(self)
		if self.Parent.__Object and self.Parent.__Property then
			local property = GetTrueObject(self.Parent.__Object).Property[self.Parent.__Property]
			local propType = IGAS:GetPropertyType(property.Type)

			if propType["Type"] == "number" then
				-- Refresh, maybe changed
				self.Text = string.format("%.1f", self.Parent.__Object[self.Parent.__Property] or 0)

			elseif propType["Type"] == "string" then
				-- Refresh, maybe changed
				self.Text = tostring(self.Parent.__Object[self.Parent.__Property] or "")

			elseif propType["Type"] == "boolean" then
				-- Refresh, maybe changed
				self.Text = tostring((self.Parent.__Object[self.Parent.__Property] and true) or false)

			elseif propType["Type"] == "enum" then
				-- Refresh, maybe changed
				self.Text = tostring(self.Parent.__Object[self.Parent.__Property])
			end
		end
	end

	local function Set_OnValueChanged(self, value)
		SetPropValue(self)
	end

	local function Set_OnEnterPressed(self)
		local nextSet = self.Parent.Parent:GetChild("PropertySet"..(self.Parent.ID + 1))

		if nextSet and nextSet.Visible then
			nextSet.Set:SetFocus()
		else
			SetPropValue(self)
		end
	end

	local function Set_OnEditFocusGained(self)
		GetPropValue(self)
	end

	local function Set_OnEditFocusLost(self)
		SetPropValue(self)
	end

	local function Advance_Click(self)
		self:FireEvent("IGAS_STUDIO_PROPERTY_ADVANCE", self.Parent.Parent.__Object, self.Parent.Parent.__Property)
		return true
	end

	-- ScriptType
	local _ScriptType = {
		["OnPropertyChanged"] = true,
	}

	-- Function
	local _Function = {
		-- SetProperty
		["SetProperty"] = function (self, object, prop)
			local property
			local propType

			self.Set.DropdownBtn:UnStackScript("OnClick", Advance_Click)

			if object and prop then
				self.__Object = object
				self.__Property = prop

				property = GetTrueObject(object).Property[prop]

				propType = IGAS:GetPropertyType(property.Type)

				self.Title.Text = prop
				
				if propType["Type"] == "number" then
					-- No need dropDown
					self.Set.DropdownBtn.Visible = false
					self.Set.Editable = true

					self.Set.Text = string.format("%.1f", object[prop] or 0)
				elseif propType["Type"] == "string" then
					-- No need dropDown
					self.Set.DropdownBtn.Visible = false
					self.Set.Editable = true

					self.Set.Text = tostring(object[prop] or "")
				else
					-- Show DropDownBtn
					self.Set.DropdownBtn.Visible = true
					self.Set.Editable = false

					if propType["Type"] == "boolean" then
						self.Set:Clear()
						self.Set:AddItem(false, "false")
						self.Set:AddItem(true, "true")

						self.Set.Text = tostring((object[prop] and true) or false)
					elseif propType["Type"] == "enum" then
						self.Set:SetList(propType["EnumType"])

						self.Set.Text = tostring(object[prop])
					elseif propType["Type"] == "table" then
						self.Set.DropdownBtn:StackScript("OnClick", Advance_Click)

						self.Set.Text = "(Advance)"
					end
				end
			else
				self.__Object = nil
				self.__Property = nil
				self.Title.Text = ""
				self.Set:Clear()
				self.Set.Editable = false
			end
		end,
    }

	-- Property
	local _Property = {
    }

    -- New
    local function _New(name, parent)
		local index = parent.__NodeNum or 0
		index = index + 1

		local frame = CreateFrame("Frame",name,parent)
		frame.ID = index
		parent.__NodeNum = index
		parent.Height = parent.Height + nodeHeight

        frame:SetWidth(200)
        frame:SetHeight(nodeHeight)

		if index == 1 then
			frame:SetPoint("TOPRIGHT", parent, "TOPRIGHT", 0, - nodeHeight)
			frame:SetPoint("TOPLEFT", parent, "TOPLEFT", nodeIndent, - nodeHeight)
		else
			frame:SetPoint("TOPRIGHT", parent:GetChild("PropertySet"..(index-1)), "BOTTOMRIGHT", 0, 0)
			frame:SetPoint("TOPLEFT", parent:GetChild("PropertySet"..(index-1)), "BOTTOMLEFT", 0, 0)
		end

		frame:SetBackdrop(_FrameBackdrop)
		frame:SetBackdropColor(0,0,0,1)
		--frame:SetBackdropBorderColor(0.8, 0.8, 0.8, 0.8)

		local title = CreateFrame("FontString","Title",frame,"OVERLAY","GameFontNormal")
		title:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, 0)
		title:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 0, 0)
		title:SetPoint("RIGHT", frame, "CENTER", -10, 0)

		local cbo = CreateFrame("ComboBox", "Set", frame)
		cbo:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, 0)
		cbo:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, 0)
		cbo:SetPoint("LEFT", title, "RIGHT", 0, 0)
		cbo:SetBackdrop(_FrameBackdrop)
		cbo.Editable = true
		cbo.AutoFocus = false

		cbo.OnValueChanged = Set_OnValueChanged
		cbo.OnEnterPressed = Set_OnEnterPressed
		cbo.OnEditFocusGained = Set_OnEditFocusGained
		cbo.OnEditFocusLost = Set_OnEditFocusLost

        return frame
    end

    local _WidgetInfo = {
        ["WidgetName"] = _WidgetName,
        ["Base"] = _Base,
        ["Function"] = _Function,
        ["Property"] = _Property,
        ["ScriptType"] = _ScriptType,
        ["New"] = _New,
    }

    Widget[_WidgetName] = IGAS:NewWidget(_WidgetInfo)
end